package com.base.cn.platform.os.service.op.coupon;


import com.base.cn.platform.os.common.OpDataManage;
import com.base.cn.platform.os.common.msg.WXTmpEnum;
import com.base.cn.platform.os.common.mybatis.BaseBiz;
import com.base.cn.platform.os.common.mybatis.Pagination;
import com.base.cn.platform.os.common.utils.DataUtil;
import com.base.cn.platform.os.common.utils.DateUtils;
import com.base.cn.platform.os.common.utils.ObjectUtils;
import com.base.cn.platform.os.common.utils.StringUtils;
import com.base.cn.platform.os.common.utils.result.ResultUtil;
import com.base.cn.platform.os.dao.op.coupon.OpCouponDao;
import com.base.cn.platform.os.entity.op.coupon.OpCoupon;
import com.base.cn.platform.os.entity.op.coupon.OpCouponCode;
import com.base.cn.platform.os.service.course.cou.CourseService;
import com.base.cn.platform.os.service.course.open.CourseOpenService;
import com.base.cn.platform.os.service.manage.subject.SysSubjectBiz;
import com.base.cn.platform.os.service.op.affiche.tmp.SendMessage;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;


/**
 * 优惠券Biz
 * Created by ll on 2017/7/14 0014.
 */
@Service
public class OpCouponBiz extends BaseBiz<OpCoupon,OpCouponDao> {

    @Autowired
    private SysSubjectBiz sysSubjectBiz;
    @Autowired
    private CourseService courseService;
    @Autowired
    private CourseOpenService courseOpenService;
    @Autowired
    private OpCouponCodeBiz opCouponCodeBiz;
    @Autowired
    private OpCouponShopBiz opCouponShopBiz;
    @Autowired
    private OpCouponTermShopBiz opCouponTermShopBiz;
    @Autowired
    private OpCouponDao opCouponDao;
    @Autowired
    private OpCouponBiz opCouponBiz;
    @Autowired
    private SendMessage sendMessage;

    /**
     * 获取课程详情可以领取的优惠券列表
     * @param courseId 课程ID
     * @param userId 用户ID
     * @return List<OpCoupon>
     */
    public List<OpCoupon> getCourseCouponList(BigDecimal courseId,BigDecimal userId){
        Map<String,Object> course = courseService.findCourseById(courseId,false,false,false,false);
        if(course !=null){
            double realPrice = (double)course.get("realPrice");
            Map<String,Object> params = new HashMap<>();
            params.put("price",realPrice);
            params.put("courseId",courseId);
            params.put("userId",userId);
            List<OpCoupon> opCouponList = opCouponDao.getCourseCouponList(OpCoupon.class,params);
            return opCouponList;
        }
        return null;
    }

    /**
     * 查询定向发放、针对用户、且是全部用户的，并且未领取过的优惠券列表
     * @param userId 用户ID
     * @return List<OpCoupon>
     */
    public List<OpCoupon> findAllUserReceiveCouponList(BigDecimal userId){
        return opCouponDao.findAllUserReceiveCouponList(OpCoupon.class,userId);
    }

    /**
     * 查询定向发放、针对用户、且是部分购买过指定商品的用户，并且未领取过的优惠券列表
     * @param userId 用户ID
     * @return List<OpCoupon>
     */
    public List<OpCoupon> findPartPayShopUserReceiveCouponList(BigDecimal userId){
        return opCouponDao.findPartPayShopUserReceiveCouponList(OpCoupon.class,userId);
    }

    /**
     * 搜索优惠券列表
     *
     * @param coupon
     * @param page
     * @return
     */
    public PageInfo<OpCoupon> queryCouponListPage(OpCoupon coupon, Pagination page,boolean subjectData,boolean courseData,boolean openCourseData,boolean endTimeDay) {
        String whereSql = this.whereSqlCoupon(coupon);
        PageInfo<OpCoupon> opCoupons =this.findPage(whereSql,page,null);
        List<OpCoupon> coupons = opCoupons.getList();
        this.setCouponStatus(coupons);
        setSubjectAndCourseAndOpenCourseByList(coupons,subjectData,courseData,openCourseData,endTimeDay);
        opCoupons.setList(coupons);
        return opCoupons;
    }

    /**
     * 设置优惠状态
     * @param opCouponList 优惠券列表
     */
    private void setCouponStatus(List<OpCoupon> opCouponList){
        if(ObjectUtils.isNotEmpty(opCouponList)){
            Date currentTime = new Date();
            opCouponList.forEach(e->{
                if(e.getStatus().intValue()==1){
                    //未开始
                    if(e.getTimeType().intValue() ==1 && e.getBeginTime().after(currentTime)){
                        e.setStatus(0);
                    }else if((e.getTimeType().intValue()==2 || (e.getTimeType().intValue()==1 && e.getBeginTime().before(currentTime) && e.getEndTime().after(currentTime)))){//进行中
                        e.setStatus(1);
                    }else if(e.getTimeType().intValue()==1 && e.getEndTime().before(currentTime)){//已结束
                        e.setStatus(7);
                    }
                }
            });
        }
    }

    /**
     * 搜索优惠券
     *
     * @param coupon
     * @return
     */
    public List<OpCoupon> queryCouponList(OpCoupon coupon, boolean subjectData,boolean courseData,boolean openCourseData,boolean endTimeDay) {
        String whereSql = this.whereSqlCoupon(coupon);
        List<OpCoupon> opCoupons =this.find(whereSql,null,null);
        return setSubjectAndCourseAndOpenCourseByList(opCoupons,subjectData,courseData,openCourseData,endTimeDay);
    }

    /**
     * 根据IDS搜索优惠券
     * @param couponIds
     * @param subjectData
     * @param courseData
     * @param openCourseData
     * @return
     */
    public List<OpCoupon> queryOpCouponByIds(String couponIds, boolean subjectData,boolean courseData,boolean openCourseData,boolean endTimeDay){
        OpCoupon opCoupon = new OpCoupon();
        opCoupon.setCouponIds(couponIds);
        List<OpCoupon> opCoupons = this.queryCouponList(opCoupon,subjectData,courseData,openCourseData,endTimeDay);
        return opCoupons;
    }

    /**
     * 单个添加扩展数据
     * @param opCoupon
     * @param subjectData
     * @param courseData
     * @param openCourseData
     * @return
     */
    private OpCoupon setSubjectAndCourseAndOpenCourse(OpCoupon opCoupon,boolean subjectData,boolean courseData,boolean openCourseData,boolean endTimeDay){
        List<OpCoupon> opCoupons = new ArrayList<>();
        opCoupons.add(opCoupon);
        opCoupons =setSubjectAndCourseAndOpenCourseByList(opCoupons,subjectData,courseData,openCourseData,endTimeDay);
        return opCoupons.get(0);
    }

    /**
     * 列表添加扩展数据
     * @param opCoupons
     * @param subjectData
     * @param courseData
     * @param openCourseData
     * @return
     */
    private List<OpCoupon> setSubjectAndCourseAndOpenCourseByList(List<OpCoupon> opCoupons,boolean subjectData,boolean courseData,boolean openCourseData,boolean endTimeDay){
        if(ObjectUtils.isNotEmpty(opCoupons)){
            if (subjectData){
                sysSubjectBiz.setSubjectData(opCoupons,subjectData);
            }
            if (courseData){
                opCoupons =this.setCourseByCouponList(opCoupons,"course");
            }
            if (openCourseData){
                opCoupons =this.setCourseByCouponList(opCoupons,"openCourse");
            }
            if (endTimeDay){
                opCoupons =this.setEndTimeDayNum(opCoupons);
            }
        }
        return opCoupons;
    }



    /**
     * 获取Sql
     * @param coupon
     * @return
     */
    public String whereSqlCoupon(OpCoupon coupon) {
        StringBuilder whereSql = new StringBuilder(" 1=1 ");
        if (ObjectUtils.isNotEmpty(coupon)) {
            if (StringUtils.isNotEmpty(coupon.getCouponIds())){
                String couponIds = StringUtils.subHeadTailString(coupon.getCouponIds(),",");
                whereSql.append(" and id in(").append(couponIds).append(")");
            }
            if (StringUtils.isNotEmpty(coupon.getTitle())) {
                whereSql.append(" and title like concat ('%','").append(coupon.getTitle()).append("','%')");
            }
            if (StringUtils.isNotEmpty(coupon.getCouponBatch())) {
                whereSql.append(" and couponBatch like concat ('%','").append(coupon.getCouponBatch()).append("','%')");
            }
            if (coupon.getType()!=null&&coupon.getType()>0) {
                whereSql.append(" and type =").append(coupon.getType());
            }
            if(coupon.getReceiveType()!=null && coupon.getReceiveType().intValue() > 0){
                whereSql.append(" and receiveType = ").append(coupon.getReceiveType());
            }
            if(coupon.getReceiveType()!=null && coupon.getReceiveType().intValue() > 0){
                whereSql.append(" and receiveType = ").append(coupon.getReceiveType());
            }
            if(coupon.getOrientType()!=null && coupon.getOrientType().intValue() > 0){
                whereSql.append(" and orientType = ").append(coupon.getOrientType());
            }
            if(coupon.getUserType()!=null && coupon.getUserType().intValue() > 0){
                whereSql.append(" and userType = ").append(coupon.getUserType());
            }
            if (coupon.getConditions()!=null&&coupon.getConditions()>0) {
                if(coupon.getConditions()==8){//商品详情领取
                    whereSql.append(" and receiveType = 1");
                }else if(coupon.getConditions()==9){//全用户可领取
                    whereSql.append(" and receiveType = 2 and orientType =1 and userType=1");
                }else if(coupon.getConditions()==10){//部分用户可领取
                    whereSql.append(" and receiveType = 2 and orientType =1 and userType=2");
                }else if(coupon.getConditions()==11){//积分兑换
                    whereSql.append(" and `conditions` =").append(coupon.getConditions());
                    whereSql.append(" and  (integralGoodId is null  or integralGoodId='' or integralGoodId=0) ");
                }
                else{
                    whereSql.append(" and `conditions` =").append(coupon.getConditions());
                }
            }
            if (StringUtils.isNotEmpty(coupon.getOpenCourseIds())) {
                whereSql.append(" and openCourseIds like concat ('%','").append(coupon.getOpenCourseIds()).append("','%')");
            }
            if (StringUtils.isNotEmpty(coupon.getCourseIds())) {
                whereSql.append(" and courseIds like concat ('%','").append(coupon.getCourseIds()).append("','%')");
            }
            if (StringUtils.isNotEmpty(coupon.getTimeType())) {
                whereSql.append(" and timeType =").append(coupon.getTimeType());
            }
            if (StringUtils.isNotEmpty(coupon.getSummary())) {
                whereSql.append(" and summary like concat ('%','").append(coupon.getSummary() + "','%')");
            }
            if (ObjectUtils.isNotEmpty(coupon.getBeginTime())) {
                whereSql.append(" and createTime >= '").append(new SimpleDateFormat("yyyy-MM-dd").format(coupon.getBeginTime())).append(" 00:00:00'");
            }
            if (ObjectUtils.isNotEmpty(coupon.getEndTime())) {
                whereSql.append(" and createTime <= '").append(new SimpleDateFormat("yyyy-MM-dd").format(coupon.getEndTime())).append(" 23:59:59'");
            }
            if (coupon.getStatus()!=null) {
                if(coupon.getStatus()==0){//未开始
                    whereSql.append(" and status =1 and timeType=1 and beginTime > now()");
                }else if(coupon.getStatus()==1){//进行中
                    whereSql.append(" and status =1 and (timeType =2 or (timeType=1 and beginTime <= now() and endTime >= now()))");
                }else if(coupon.getStatus()==7){//已结束
                    whereSql.append(" and status =1 and timeType=1 and endTime < now()");
                }else{
                    whereSql.append(" and status =").append(coupon.getStatus());
                }
            } else {
                whereSql.append(" and status !=3");
            }
            if(StringUtils.isNotEmpty(coupon.getSubjectIds())){
                whereSql.append(StringUtils.getSubjectSql("subjectIds",coupon.getSubjectIds()));
            }
        }
        whereSql.append(" order by id desc");
        return whereSql.toString();
    }

    /**
     * 搜索优惠券详情
     * @param id
     * @return
     */
    public OpCoupon queryOpCouponById(BigDecimal id,boolean subjectData,boolean courseData,boolean openCourseData,boolean endTimeDay){
        if(DataUtil.idIsNotNull(id)){
            OpCoupon opCoupon = this.findById(id);
            return setSubjectAndCourseAndOpenCourse(opCoupon,subjectData,courseData,openCourseData,endTimeDay);
        }
        return null;
    }



    /**
     * 添加优惠券
     *
     * @param coupon
     * @return
     */
    @Transactional(rollbackFor =  IllegalArgumentException.class)
    public OpCoupon txSaveCoupon(OpCoupon coupon) {
        if (ObjectUtils.isNotEmpty(coupon)) {
            coupon.setStatus(1);
            this.save(coupon);
            this.generateCouponCode(coupon);
            //保存优惠券关联的商品数据
            opCouponShopBiz.saveCouponShopData(coupon);
            //创建优惠券推广设置的指定商品付费用户
            opCouponTermShopBiz.createCouponTermShop(coupon.getOpCouponTermShopList(),coupon.getId());
        }
        return coupon;
    }

    /**
     * 生成优惠券编码
     *
     * @param coupon 优惠券
     */
    public void generateCouponCode(OpCoupon coupon) {
        //如果未生成优惠券编码
        Integer generateCount = coupon.getCodeNum();
        List<OpCouponCode> codeList = new LinkedList<>();
        Date currentTime = new Date();
        IntStream.range(0,generateCount.intValue()).forEach(index->{
            String code = StringUtils.handleStrValue(DateUtils.format(currentTime, "yyyyMMddHHmmssSSS") + index).substring(0, 20); //优惠券编码
            OpCouponCode couponCode = new OpCouponCode();
            couponCode.setCode(code);
            couponCode.setCouponId(coupon.getId());
            couponCode.setType(coupon.getType());
            couponCode.setLimitAtion(coupon.getLimitAtion());
            couponCode.setReceiveType(coupon.getReceiveType());
            couponCode.setOrientType(coupon.getOrientType());
            couponCode.setUserType(coupon.getUserType());
            couponCode.setConditions(coupon.getConditions());
            couponCode.setStatus(1);
            couponCode.setTimeType(coupon.getTimeType());
            if (coupon.getTimeType() == 1) {
                couponCode.setBeginTime(coupon.getBeginTime());
                couponCode.setEndTime(coupon.getEndTime());
            }
            couponCode.setOpenCourseIds(coupon.getOpenCourseIds());
            couponCode.setSettingStatus(coupon.getSettingStatus());
            couponCode.setCourseIds(coupon.getCourseIds());
            couponCode.setMinAmount(coupon.getMinAmount());
            codeList.add(couponCode);
        });
        opCouponCodeBiz.batchSave(codeList);
    }

    /**
     * 批量停止，删除，恢复
     *
     * @param couponIds 优惠券id
     * @param status    优惠券状态 1.正常 2.停止 3.删除
     */
    @Transactional(rollbackFor =  IllegalArgumentException.class)
    public List<OpCoupon> updateCouponStatus(String couponIds, Integer status) {
        List<String> containColumns = new ArrayList<>();
        containColumns.add("codeNum");
        containColumns.add("useCount");
        containColumns.add("timeType");
        containColumns.add("beginTime");
        containColumns.add("endTime");
        containColumns.add("status");
        containColumns.add("id");
        //获取优惠券数据列表
        List<OpCoupon> couponList = find("id in("+couponIds+")",null,containColumns);
        // 更新优惠券
        if(ObjectUtils.isNotEmpty(couponList)){
            List<OpCoupon> _couponList = new ArrayList<>();
            couponList.forEach(e->{
                OpCoupon coupon = new OpCoupon();
                coupon.setId(e.getId());
                coupon.setStatus(e.getStatus());
                coupon.setEndTime(e.getEndTime());
                coupon.setBeginTime(e.getBeginTime());
                coupon.setTimeType(e.getTimeType());
                coupon.setUseCount(e.getUseCount());
                coupon.setCodeNum(e.getCodeNum());
                _couponList.add(coupon);
            });
            this.setCouponStatus(_couponList);
            Map<Boolean,List<OpCoupon>> couponListMap = _couponList.stream().collect(Collectors.groupingBy(e->e.getStatus().intValue()==7));
            List<OpCoupon> _List = couponListMap.get(false);//未结束的
            if(ObjectUtils.isNotEmpty(_List)){
                _List.forEach(e->{
                    e.setStatus(status);
                });
                updateBatch(_List);
                String _couponIds = _List.stream().map(e->e.getId().toString()).collect(Collectors.joining(","));
                //同时修改优惠券的编码
                OpCouponCode couponCode = new OpCouponCode();
                couponCode.setStatus(status);
                opCouponCodeBiz.updateByWhereSql(couponCode, " couponId in (" + _couponIds + ") and userId =0");
                //设置状态
                this.setCouponStatus(_List);
                return _List;
            }
        }
        return null;
    }


    /**
     * 赠送优惠券
     */
    public void presentCoupon(List<OpCouponCode> opCouponCodes) {
        opCouponCodeBiz.updateBatch(opCouponCodes);

        //发送消息
        Map<BigDecimal,List<OpCouponCode>> codeListMap = opCouponCodes.stream().collect(Collectors.groupingBy(e->e.getUserId()));
        List<BigDecimal> userIdList = new ArrayList<>(codeListMap.keySet());
        Map<BigDecimal,List> dataListMap = new HashMap<>();
        codeListMap.forEach((k,v)->{
            dataListMap.put(k,v);
        });
        sendMessage.sendMessage(WXTmpEnum.COUPON_CODE,userIdList,dataListMap);
    }

    /**
     * 赠送用户优惠券
     *
     * @param userId    用户ID
     * @param couponIds 优惠券ID
     * @param count     赠送量
     */
    public void presentCoupon(BigDecimal userId, String couponIds, int count) {
        if (DataUtil.idIsNotNull(userId) && StringUtils.isNotEmpty(couponIds) && count > 0) {
            couponIds = StringUtils.subHeadTailString(couponIds, ",");
            List<OpCouponCode> couponCodeList = opCouponCodeBiz.find(" (userId is null or userId = 0) and couponId in (" + couponIds + ") and endTime >= '" + DateUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss") + "' and status = 1 or timeType = 2",null,null);
            if (ObjectUtils.isNotEmpty(couponCodeList)) {
                Map<BigDecimal, List<OpCouponCode>> couponCodeListMap = couponCodeList.stream().collect(Collectors.groupingBy(OpCouponCode::getCouponId));
                String[] arr = couponIds.split(",");
                List<OpCouponCode> allList = new ArrayList<>();
                for (String str : arr) {
                    List<OpCouponCode> _list = couponCodeListMap.get(Long.parseLong(str));
                    if (ObjectUtils.isNotEmpty(_list)) {
                        if (_list.size() > count) {
                            for (int i = 0; i < count; i++) {
                                allList.add(_list.get(i));
                            }
                        } else {
                            allList.addAll(_list);
                        }
                    }
                }
                if (ObjectUtils.isNotEmpty(allList)) {
                    for (OpCouponCode couponCode : allList) {
                        couponCode.setUserId(userId);
                    }
                    opCouponCodeBiz.updateBatch(allList);
                }
            }
        }
    }

    /**
     * 积分兑换商品发放
     * @param userId
     * @param couponId
     * @return
     */
    public  Map exchangeCoupon(BigDecimal userId,BigDecimal couponId){
        List<OpCouponCode> couponList = opCouponCodeBiz.queryOpCouponCodeByGiftCardIdAndStatusAndIsUserData(couponId,1,null,1);
        if (!ObjectUtils.isNotEmpty(couponList)) {
            return ResultUtil.ERROR("商品库存不足","10000");
        }
        couponList.get(0).setUserId(userId);
        //发放优惠券
        opCouponCodeBiz.updateBatch(couponList);
       return ResultUtil.SUCCESS("兑换成功",couponList.get(0).getId());
    }


    /**
     * 给优惠券添加 课程  或 免费直播成
     *
     * @param str     'course'  'openCourse'
     * @param coupons
     */
    public List<OpCoupon> setCourseByCouponList(List<OpCoupon> coupons, String str) {
        if (ObjectUtils.isNotEmpty(coupons)) {
            String couponCourse = "";
            for (OpCoupon coupon : coupons) {
                if (str.equals("course") && StringUtils.isNotEmpty(coupon.getCourseIds())) {
                    couponCourse += StringUtils.subHeadTailString(coupon.getCourseIds(), ",") + ",";
                }
                if (str.equals("openCourse") && StringUtils.isNotEmpty(coupon.getOpenCourseIds())) {
                    couponCourse += StringUtils.subHeadTailString(coupon.getOpenCourseIds(), ",") + ",";
                }
            }
            String courseIds = OpDataManage.getCourseId(couponCourse);
            Map<BigDecimal, Map<String, Object>> courseMap = null;
            if (StringUtils.isNotEmpty(courseIds)) {
                if (str.equals("course")) {
                    courseMap = courseService.findCourseToMapByIds(courseIds,false,false,false);
                }
                if (str.equals("openCourse")) {
                    courseMap = courseOpenService.findCourseOpenMapByIds(courseIds,false,false,false);
                }
            }
            if (ObjectUtils.isNotEmpty(courseMap)) {
                List<BigDecimal> courseIdList = new ArrayList<>(courseMap.keySet());
                for (OpCoupon coupon : coupons) {
                    List<Map<String, Object>> courseListMap = new ArrayList<>();
                    for (BigDecimal courseId : courseIdList) {
                        if (StringUtils.isNotEmpty(coupon.getCourseIds())){
                            if (coupon.getCourseIds().contains("," + courseId.toString() + ",") && str.equals("course")) {
                                courseListMap.add(courseMap.get(courseId));
                            }
                        }
                        if (StringUtils.isNotEmpty(coupon.getOpenCourseIds())){
                            if (coupon.getOpenCourseIds().contains("," + courseId.toString() + ",") && str.equals("openCourse")) {
                                courseListMap.add(courseMap.get(courseId));
                            }
                        }
                    }
                    if (str.equals("course")) {
                        coupon.setCourseList(courseListMap);
                    }
                    if (str.equals("openCourse")) {
                        coupon.setOpenCourseList(courseListMap);
                    }
                }
            }
        }
        return coupons;
    }

    /**
     * 添加过期天数
     * @param coupons
     */
    public List<OpCoupon> setEndTimeDayNum(List<OpCoupon> coupons) {
        if (ObjectUtils.isNotEmpty(coupons)) {
            for (OpCoupon coupon : coupons) {
                if (coupon.getTimeType() == 1) {
                    Integer day = DateUtils.daysBeforeNow(coupon.getEndTime());
                    coupon.setEndDayNum(day);
                }
            }
        }
        return coupons;
    }
}